import { store } from "./store"
import * as Utils from "./utils"

const web3 = window.Web3

const NETID_MAP = {
    1: "Main",
    3: "Ropsten",
    42: "Kovan",
    4: "Rinkeby",
}
const GetInfo = async (web3) => {
    let acct = await web3.eth.getCoinbase()
    let netId = await web3.eth.net.getId()
    let chainId = await web3.eth.getChainId()
    return {
        acct,
        netId,
        chainId,
        name: NETID_MAP[netId],
    }
}

const getDefaultProvider = () => {
    const provider = window['ethereum'] || (window.web3 && window.web3.currentProvider)
    return provider;
}

const ConnectWallet = async (callback) => {
    if (window.ethereum) {
        console.log("there is a default browser wallet.")
        let provider = getDefaultProvider()
        if (provider) {
            store.wallet = new window.Web3(provider)

            window.ethereum.on("accountsChanged", callback)
            return store.wallet
        } else {
            throw Error("get default provider error.")
        }
    } 
    throw Error("no defualt provider")
}


const PersistentData = (key, value, op="save") => {
    if (op !== 'save') {
        return window.localStorage.getItem(key)
    } else {
        window.localStorage.setItem(key, value)
        return "ok"
    }
}

const ContractGet = async (w3, abi, address) => {
    let saveKey = address + "-abi"
    if (store.contract[saveKey]) {
        return store.contract[saveKey]
    }
    if (!abi || !abi.trim()) {
        console.log("%c get abi from local", "background:black;color:white;padding:3px;")
        abi = PersistentData(saveKey, "", "get")
        if (!abi) {
            throw Error("Please provide ABI of " + address)
        }
    }
    let abiObj = JSON.parse(abi)
    let result = new w3.eth.Contract(abiObj, address)
    PersistentData(saveKey, abi)
    store.contract[saveKey] = result
    return result
}
const ContractGetInfo = async (w3, abi, address) => {
    let needKeys = ["defaultChain", "defaultAccount", "methods"]
    let contract = await ContractGet(w3, abi, address)
    let result = {}
    for (let x of needKeys) {
        result[x] = contract[x]
    }

    if (contract.events) {
        result.events = Object.keys(contract.events).filter(v => Utils.matchEventName(v))
    } else {
        result.events = []
    }
    console.log("events:", result.events)
    return result
}
const ContractSet = async (w3, abi, address, options) => {
    let contract = await ContractGet(w3, abi, address)
    // console.log("TRY SET CONTRACT", contract)
    for (let option in options) {
        contract.options[option] = options[option]
    }
    return contract
}
const CallContractMethod = async (w3, abi, address, methodName, param, type="call") => {
    let contract = await ContractGet(w3, abi, address)
    let method = contract.methods[methodName](...param)
    if (type == 'call') {
        console.log(`[${methodName}] call`)
        return await method.call()
    } else {
        console.log(`[${methodName}] send`)
        return await method.send()
    }
}
export {
    GetInfo,
    ConnectWallet,
    ContractGet,
    ContractGetInfo,
    CallContractMethod,
    ContractSet,
    Utils,
}